package com.ems.remote.components;

import com.ems.service.IDeviceService;
import com.ems.util.*;
import com.ems.vo.DeviceVo;
import com.ems.vo.PcsVo;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @Author: Wuzh
 * @Description:由平台系统下发EMS，控制PCS的开关机操作
 * @Date Created in 20:23 2024-05-08
 * @return
 */
@Component
@Slf4j
public class PcsRequestStrategy {

    @Resource
    private IDeviceService iDeviceService;

    /**
     * 0c
     * 000a：数据长度
     * 0b：命令码
     * 2b5e：设备地址，PCS
     * 01：一个数据
     * YKID：两字节Id，对应云平台点表
     * YKValue：四字节控制值
     * 校验和
     * 终止码
     */
    public void request (PcsVo pcsVo) {
        log.info ( "控制PCS开关机" );
        DeviceVo deviceVo = new DeviceVo ();
        deviceVo.setDeviceAddress ( pcsVo.getDeviceAddress () );
        deviceVo = iDeviceService.querySingle ( deviceVo );
        Channel channel = start ( deviceVo );
        byte value = 0x00;
        if ( deviceVo.getConnectStatus () == 1 ) {
            //已开机，进行关机操作
            value = 0x00;
            deviceVo.setConnectStatus ( 0 );
        } else {
            value = 0x01;
            deviceVo.setConnectStatus ( 1 );
        }
        //重新更新设备开机状态
        log.info ( "设备地址：->{}", deviceVo.getDeviceAddress () );
        String key = deviceVo.getDeviceAddress ().concat ( "#connect" );
        RedisUtils.set ( key, String.valueOf ( value ) );
        //解决设备地址
        String deviceAddress = deviceVo.getDeviceAddress ();//11102
        byte[] bitAddress = HexUtil.hexToTwoBytes ( deviceAddress );
        //开关机测点Id的十六进制
        Integer pcsPowerOnOffComm = EmsPointUtil.PCS_POWER_ON_OFF_COMM;
        byte[] bytes = {0x00, 0x00, 0x00, value};
        send ( channel, bitAddress, pcsPowerOnOffComm, bytes );
    }

    /**
     * PCS故障复位
     * @param pcsVo
     */
    public void alarmRest (PcsVo pcsVo) {
        log.info ( "PCS故障复位" );
        DeviceVo deviceVo = new DeviceVo ();
        deviceVo.setDeviceAddress ( pcsVo.getDeviceAddress () );
        deviceVo = iDeviceService.querySingle ( deviceVo );
        Channel channel = start ( deviceVo );
        //解决设备地址
        String deviceAddress = deviceVo.getDeviceAddress ();//11102
        byte[] bitAddress = HexUtil.hexToTwoBytes ( deviceAddress );
        // PCS故障复位
        Integer resetComm = EmsPointUtil.PCS_FAIL_RESET_COMM;
        byte[] bytes = {0x00, 0x00, 0x00, 0x00};
        send ( channel, bitAddress, resetComm, bytes );
    }

    /**
     * PCS离网模式设置
     * @param pcsVo
     */
    public void offGird (PcsVo pcsVo) {
        log.info ( "PCS离网模式设置" );
        DeviceVo deviceVo = new DeviceVo ();
        deviceVo.setDeviceAddress ( pcsVo.getDeviceAddress () );
        deviceVo = iDeviceService.querySingle ( deviceVo );
        Channel channel = start ( deviceVo );
        //解决设备地址
        String deviceAddress = deviceVo.getDeviceAddress ();
        byte[] bitAddress = HexUtil.hexToTwoBytes ( deviceAddress );
        // PCS离网模式测点
        Integer offGrid = EmsPointUtil.PCS_OFF_GRID_MODEL_SET;
        // 获取设备离网模式值
        byte value = 0x00;
        if ( deviceVo.getOffGridStatus () == 0 ) {
            //并网模式
            value = 0x01;
            deviceVo.setOffGridStatus ( 1 );
        } else {
            value = 0x00;
            deviceVo.setOffGridStatus ( 0 );
        }
        String key = deviceVo.getDeviceAddress ().concat ( "#offGrid" );
        RedisUtils.set ( key, String.valueOf ( value ) );
        byte[] bytes = {0x00, 0x00, 0x00, value};
        send ( channel, bitAddress, offGrid, bytes );
    }

    /**
     * 设置PCS下发充放电功率
     * @param deviceVo
     */
    public void setChargeDisPower (DeviceVo deviceVo) {
        log.info ( "设置PCS充放电功率，充放电功率值：{}", deviceVo.getChargeDisPower () );
        Channel channel = start ( deviceVo );
        //解决设备地址
        String deviceAddress = deviceVo.getDeviceAddress ();
        byte[] bitAddress = HexUtil.hexToTwoBytes ( deviceAddress );
        log.info ( "地址两字节：[{} {}]", bitAddress[0], bitAddress[1] );
        // PCS离网模式测点
        Integer chargePower = EmsPointUtil.PCS_DIS_CHARGE_POWER;
        //解决充放电功率值的问题
        Integer n = Integer.parseInt ( deviceVo.getChargeDisPower () );
        String hexString = Integer.toHexString ( n );
        byte[] byteArray = HexUtil.hexStringToByteArray ( hexString );
        log.info ( "充放电值四字节：[{} {} {} {}]", byteArray[0], byteArray[1], byteArray[2], byteArray[3] );
        String key = deviceVo.getDeviceAddress ().concat ( "#power" );
        RedisUtils.set ( key, String.valueOf ( deviceVo.getChargeDisPower () ) );
        send ( channel, bitAddress, chargePower, byteArray );
    }

    /**
     * 够获取通道
     * @param deviceVo
     * @return
     */
    public Channel start (DeviceVo deviceVo) {
        String s = Integer.toHexString ( Integer.parseInt ( deviceVo.getDeviceAddress () ) );
        Channel channel = ChannelMap.getChannel ( s );
        log.info ( "channel通道->{}", channel );
        return channel;
    }

    /**
     * 下发控制PCS
     * @param channel：通道
     * @param bitAddress：设备地址
     * @param point：两字节测点Id
     * @param value：四字节测点值
     */
    public void send (Channel channel, byte[] bitAddress, int point, byte[] value) {
        //测点Id，取云平台对应Id
        byte[] pointByte = HexUtil.hexToTwoBytes ( String.valueOf ( point ) );
        byte[] bytes = {0x00, 0x07, 0x0b, bitAddress[0], bitAddress[1], 0x01, pointByte[0], pointByte[1], value[0], value[1], value[2], value[3]};
        byte crc = EmsCRC8.emsCrc ( bytes, 12 );
        log.info ( "crc->{}", crc );
        //响应数据
        byte[] re = {0x0c, 0x00, 0x07, 0x0b, bitAddress[0], bitAddress[1], 0x01, pointByte[0], pointByte[1], value[0], value[1], value[2], value[3], crc, 0x0d};
        log.info ( "响应数据->{}", re );
        channel.writeAndFlush ( re );
    }

}
